using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Media; // 添加此行
using System.Windows.Shapes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Win32;


namespace NodeEditor {
	public partial class NodeGraph : Border {

		public readonly NodeGraphContext context;
        private MainWindow _window;

		private Node _selectedNode;
        public Node selectNode {
            get {
                return _selectedNode;
            }
        }

        private Node rootNode;

        private Path _selectedPipe;
        private Brush _selectedPipeBrush;

        private ContextMenu _contextMenu;

		private double _pipeStiffness = 50;
        public double pipeStiffness {
            get {
                return _pipeStiffness;
            }
            set {
                if (_pipeStiffness == value)
                    return;
            }
        }

        private ScaleTransform scaleTransform;
        private TranslateTransform translateTransform;

        private TextBlock filePathTextBlock;

		public NodeGraph(NodeGraphContext context, MainWindow window) {
			InitializeComponent();
			this.context = context;
            this._window = window;
            this.rootNode = null;

            canvas.MouseLeftButtonDown += OnMouseLeftButtonDown;
            canvas.MouseRightButtonDown += OnMouseRightButtonDown; // 添加右键事件

            // 初始化变换
            var transformGroup = new TransformGroup();
            scaleTransform = new ScaleTransform(1, 1);
            translateTransform = new TranslateTransform(0, 0);
            transformGroup.Children.Add(scaleTransform);
            transformGroup.Children.Add(translateTransform);
            this.RenderTransform = transformGroup;

            MouseWheel += NodeGraph_MouseWheel;

            // 添加键盘事件监听
            KeyDown += NodeGraph_KeyDown;

            // 初始化 ContextMenu
            _contextMenu = new ContextMenu();
            var createNodeItem = new MenuItem { Header = "创建节点" };
            createNodeItem.Click += CreateNodeItem_Click;
            _contextMenu.Items.Add(createNodeItem);

            // 创建 TextBlock
            filePathTextBlock = new TextBlock {
                Foreground = Brushes.White,
                HorizontalAlignment = HorizontalAlignment.Left,
                VerticalAlignment = VerticalAlignment.Bottom,
            };
            // 添加到 canvas
            canvas.Children.Add(filePathTextBlock);

            // 初始化状态文本块
            SetfilePathTextBlock("no save file");
		}

        private void SetfilePathTextBlock(string txt) {
            filePathTextBlock.Text = txt;
        }

        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            if (Pipe.EditingPipe != null && (Mouse.DirectlyOver == this || Mouse.DirectlyOver == canvas)) {
                Pipe.EditingPipe.Dispose();
                Pipe.EditingPipe = null;
            }

            // 取消之前选中的连线高亮
            if (_selectedPipe != null) {
                _selectedPipe.Stroke = _selectedPipeBrush;
            }

            // 判断点击的元素是否是 Path
            if (e.OriginalSource is Path path) {
                _selectedPipeBrush = path.Stroke;
                _selectedPipe = path;
                _selectedPipe.Stroke = new SolidColorBrush(Color.FromArgb(128, 255, 255, 255)); // 设置为淡白色
            } else {
                _selectedPipeBrush = null;
                _selectedPipe = null;
            }

            if (Mouse.DirectlyOver == canvas || _selectedPipe != null) {
                // 点击空白区域时取消选中
                SelectNode(null);
            }
        }

        public void SelectNode(Node node) {
            if (_selectedNode == node) {
                return;
            }

        	if (_selectedNode != null) {
        		_selectedNode.IsSelected = false; // 取消之前选中的节点
        	}

        	_selectedNode = node;
        	if (_selectedNode != null) {
        		_selectedNode.IsSelected = true; // 设置当前节点为选中状态
        	}
            _window.ChangeNodeEnabled(node);
        }

        // 鼠标滚轮缩放
        private void NodeGraph_MouseWheel(object sender, MouseWheelEventArgs e) {
            double zoomFactor = e.Delta > 0 ? 1.1 : 0.9; // 放大或缩小
            Point mousePosition = e.GetPosition(this);

            // 调整缩放中心
            scaleTransform.CenterX = mousePosition.X;
            scaleTransform.CenterY = mousePosition.Y;

            // 应用缩放
            scaleTransform.ScaleX *= zoomFactor;
            scaleTransform.ScaleY *= zoomFactor;
        }

        // 键盘事件处理
        private void NodeGraph_KeyDown(object sender, KeyEventArgs e) {
            if (e.Key == Key.Delete) {
                if (_selectedPipe != null) {
                    // 删除连线
                    if (_selectedPipe.Tag is UIElement relatedElement && canvas.Children.Contains(relatedElement)) {
                        Path path = (Path)_selectedPipe.Tag;
                        Pipe pipe = (Pipe)path.Tag;
                        pipe.Dispose();
                    }

                    // 清空选中连线
                    _selectedPipe = null;
                    _selectedPipeBrush = null;
                }

                if (_selectedNode != null) {
                    // 根节点不能删除，因为保存到磁盘时，得通过根节点遍历其下的所有节点
                    if (_selectedNode == rootNode) {
                        return;
                    }

                    // 删除与该节点相关的连线
                    _selectedNode.Dispose();

                    // 从 canvas 中移除节点
                    if (canvas.Children.Contains(_selectedNode)) {
                        canvas.Children.Remove(_selectedNode);
                    }

                    // 清空选中节点
                    SelectNode(null);
                }
            }

            if (Keyboard.IsKeyDown(Key.LeftCtrl) && e.Key == Key.V) {
                // 复制节点
                if (_selectedNode != null) {
                    CopyNode();
                }
            }
        }

        private void CopyNode() {
            double x = _selectedNode.position.X + _selectedNode.ActualWidth;
            double y = _selectedNode.position.Y + _selectedNode.ActualHeight;
            Node cpNode = addNode(x, y);
            cpNode.title = _selectedNode.title;
            cpNode.desc = _selectedNode.desc;
            cpNode.LoadAllVar(_selectedNode.CopyNodeVarList());
        }

        private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e) {
            // 获取鼠标点击位置
            Point mousePosition = e.GetPosition(canvas);

            // 动态更新 ContextMenu 的位置
            _contextMenu.PlacementTarget = canvas;
            _contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;

            // 显示 ContextMenu
            _contextMenu.IsOpen = true;

            // 防止事件继续传播
            e.Handled = true;
        }

        private void CreateNodeItem_Click(object sender, RoutedEventArgs e) {
            // 获取鼠标点击位置
            Point mousePosition = Mouse.GetPosition(canvas);
            addNode(mousePosition.X, mousePosition.Y);
        }

        public Node addNode(double x, double y) {
            // 创建节点并设置位置
            Node newNode = new JsonNode {
                position = new Point(x, y)
            };

            // 添加节点到 canvas
            return addNode(newNode);
        }

		public Node addNode(Node node) {
            if (rootNode == null) {
                rootNode = node;
                // 橙色背景
                var converter = new BrushConverter();
                rootNode.Background = (Brush)converter.ConvertFromString("#F0A30A");
            }

            canvas.Children.Add(node);
            node.setConnections();
            return node;
        }

        private Dictionary<int, bool> filterNodeMap = new Dictionary<int, bool>();
        // 配置 JsonSerializer，忽略 null 值
        private JsonSerializer jsonSerializer = new JsonSerializer {
            NullValueHandling = NullValueHandling.Ignore
        };

        public void SaveNodeTreeToJsonByCtrlS(List<VarData> globalVarList) {
            if (filePathTextBlock.Text != "") {
                SaveNodeTreeToJson(filePathTextBlock.Text, globalVarList);
            } else {
                OpenSaveJsonDialog(globalVarList);
            }
        }

        public void OpenSaveJsonDialog(List<VarData> globalVarList) {
            if (rootNode == null) {
                MessageBox.Show("Please add a node to save.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "JSON Files (*.json)|*.json"; // 设置文件过滤器
            saveFileDialog.Title = "Save Node File"; // 设置对话框标题
            saveFileDialog.DefaultExt = ".json"; // 设置默认文件扩展名
 
            // 显示保存对话框
            bool? result = saveFileDialog.ShowDialog();
            if (result == true) // 如果用户点击了"Save"按钮
            {
                string filename = saveFileDialog.FileName; // 获取用户选择的文件路径
                // 这里编写保存JSON文件的代码
                SaveNodeTreeToJson(filename, globalVarList);
            }
        }

        public void SaveNodeTreeToJson(string filePath, List<VarData> globalVarList) {
            filterNodeMap.Clear();

            JObject jsonObject = new JObject();
            JArray nodeList = new JArray();

            CoverNodeToJson(nodeList, rootNode);
            ForeachNodeToJson(nodeList, rootNode);

            if (globalVarList != null && globalVarList.Count > 0) {
                JArray jsonArray = JArray.FromObject(globalVarList, jsonSerializer);
                jsonObject.Add("Globals", jsonArray);
            }

            jsonObject.Add("Nodes", nodeList);
            filterNodeMap.Clear();

            System.IO.File.WriteAllText(filePath, jsonObject.ToString());
            SetfilePathTextBlock(filePath);
        }

        public void CoverNodeToJson(JArray nodeList, Node node) {
            filterNodeMap[node.uid] = true;

            Vector2 pos;
            pos.x = node.position.X;
            pos.y = node.position.Y;

            var varList = node.GetAllVar();
            JsonFullNode fullNode = new JsonFullNode {
                uid = node.uid,
                name = node.title,
                desc = node.desc,
                varList = varList.Count > 0 ? varList : null,
                nextNodes = GetNextAllNodeUid(node),
                pos = pos,
            };
            JObject nodeJson = JObject.FromObject(fullNode, jsonSerializer);
            nodeList.Add(nodeJson);
        }

        public void ForeachNodeToJson(JArray nodeList, Node curNode) {
            foreach (OutputDock output in curNode.getOutputs()) {
                foreach (Pipe pipe in output.pipes.ToArray()) {
                    Node node = pipe.inputDock.node;
                    if (filterNodeMap.ContainsKey(node.uid)) {
                        continue;
                    }

                    CoverNodeToJson(nodeList, node);
                    ForeachNodeToJson(nodeList, node);
                }
            }
        }

        // 连线信息，连线思路：主要是获取当前节点的子节点有哪些，然后根据当前节点和子节点进行连线
        public List<int> GetNextAllNodeUid(Node curNode) {
            List<int> tmp = new List<int>();
            foreach (OutputDock output in curNode.getOutputs()) {
                foreach (Pipe pipe in output.pipes.ToArray()) {
                    Node node = pipe.inputDock.node;
                    tmp.Add(node.uid);
                }
            }
            return tmp.Count > 0 ? tmp : null;
        }

        public void OpenLoadJsonDialog() {
            // 创建OpenFileDialog实例
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "JSON files (*.json)|*.json|All files (*.*)|*.*"; // 设置过滤器
            openFileDialog.Title = "选择一个JSON文件"; // 设置对话框标题
 
            // 显示对话框并检查结果
            if (openFileDialog.ShowDialog() == true) {
                // 获取选中的文件路径
                string filePath = openFileDialog.FileName;
                try {
                    canvas.Children.Clear();

                    // 读取文件内容到字符串
                    string jsonContent = System.IO.File.ReadAllText(filePath);
                    LoadJsonString(jsonContent);
                    SetfilePathTextBlock(filePath);
                    canvas.Children.Add(filePathTextBlock);
                }
                catch (Exception ex) {
                    MessageBox.Show("读取或解析文件时发生错误: " + ex.Message + " " + ex.StackTrace);
                }
            }
        }

        private void LoadJsonString(string jContent) {
            Dictionary<int, Node> pipeNodes = new Dictionary<int, Node>();
            Dictionary<int, JsonFullNode> jFullNode = new Dictionary<int, JsonFullNode>();
            JObject jsonObject = JObject.Parse(jContent);

            JArray jsonArray = (JArray)jsonObject["Globals"];
            if (jsonArray != null) {
                foreach (var item in jsonArray) {
                    VarData v = item.ToObject<VarData>();
                    _window.AddGlobalVar(v.type, v.key, v.value);
                }
            }

            JArray jNodeArray = (JArray)jsonObject["Nodes"];
            if (jNodeArray == null) {
                return;
            }

            rootNode = null;
            foreach (var item in jNodeArray) {
                JsonFullNode v = item.ToObject<JsonFullNode>();
                Node node = addNode(v.pos.x, v.pos.y);
                node.uid = v.uid;
                node.desc = v.desc;
                node.title = v.name;
                node.LoadAllVar(v.varList);
                pipeNodes[v.uid] = node;
                jFullNode[v.uid] = v;
            }

            // 两个节点之间连线
            foreach (var item in jFullNode) {
                int uid = item.Key;
                JsonFullNode v = item.Value;
                Node node = pipeNodes[uid];
                if (v.nextNodes != null && v.nextNodes.Count > 0) {
                    foreach(int uuid in v.nextNodes) {
                        Node subNode = pipeNodes[uuid];
                        Pipe pipe = new Pipe(node.getOutputs()[0], subNode.getInputs()[0]);
                        pipe.CheckIfPipeCompleted();
                    }
                }
            }
        }
	}
}